package com.cawis.util;

import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.nacos.common.utils.UuidUtils;
import com.cawis.annotations.HeaderName;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

@Slf4j
public class Tools {

    /**
     * 从字符串得到数字
     *
     * @param s
     * @return
     */
    public static String getNumeric(String s) {
        return Pattern.compile("[^0-9]").matcher(s).replaceAll("").trim();
    }

    /**
     * 解析数据库blob
     *
     * @param in
     * @return
     * @throws IOException
     */
    public static String getBlob(InputStream in) throws IOException {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] data = new byte[4096];
        int count = -1;
        while ((count = in.read(data, 0, 4096)) != -1)
            outStream.write(data, 0, count);
        data = null;
        String result = new String(outStream.toByteArray(), "gb2312");
        return result;
    }

    /**
     * 读取 excel
     *
     * @param inputStream
     * @param clazz
     * @param excelTypeEnum
     * @param <E>
     * @return
     */
    public static <E> List<E> readExcel(InputStream inputStream, Class<? extends BaseRowModel> clazz, ExcelTypeEnum excelTypeEnum) {
        ModelExcelListener<E> listener = new ModelExcelListener<>();
        ExcelReader excelReader = new ExcelReader(inputStream, excelTypeEnum, null, listener);
        excelReader.read(new Sheet(1, 1, clazz));
        return listener.getDataList();
    }

    @Data
    public static class ModelExcelListener<E> extends AnalysisEventListener<E> {
        private List<E> dataList = new ArrayList<E>();

        @Override
        public void invoke(E e, AnalysisContext analysisContext) {
            dataList.add(e);
        }

        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {

        }
    }

    /**
     * 导出 excel
     *
     * @param response
     * @param dataList
     * @param fileName
     * @param excelTypeEnum
     */
    public static void universalExcelExport(HttpServletResponse response, List dataList, String fileName, ExcelTypeEnum excelTypeEnum) {
        BigExcelWriter writer = (BigExcelWriter) ExcelUtil.getBigWriter();
        ServletOutputStream out;
        try {
            writer.write(dataList, true);
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + excelTypeEnum.getValue());
            out = response.getOutputStream();
            writer.flush(out, true);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            writer.close();
            IoUtil.close(writer);
            log.info("恭喜,导出成功");
        }
    }

    /**
     * 数据封装
     *
     * @param o
     * @param names
     * @return
     * @throws IllegalAccessException
     */
    public static Map entityToMap(Object o, List names) throws IllegalAccessException {
        Map maps = new LinkedHashMap();
        // 获取 实体类 中所有的字段
        Field[] declaredFields = o.getClass().getDeclaredFields();
        for (Field declaredField : declaredFields) {
            // 这里设置为 true 才可以访问到 实体类中的 private 字段
            declaredField.setAccessible(true);
            // 获取字段所对应的注解
            HeaderName annotation = declaredField.getAnnotation(HeaderName.class);
            if (null != annotation) {
                // 有注解 则 获取 注解的值（表头名称）
                String value = annotation.value();
                // 再判断 实体类中是否有这个表头
                if (names.contains(value)) {
                    maps.put(value, declaredField.get(o));
                }
            }
        }
        return maps;
    }

    public static void main(String[] args) {
        System.out.println(UuidUtils.generateUuid().replaceAll("-","").toUpperCase());
    }

}
